Object-oriented programming languages have become increasingly popular since the introduction of the C++ programming language in the mid 1980's. C++ has become the programming language of choice for many in the scientific and engineering disciplines, and has become widely known and used in the field of computer science as well. The syntax and semantics of C++ is described in detail in numerous reference books and manuals.
As used in object-oriented programming, a data "object" is a particular item of data of a specified type. For example, a given program variable may contain an object which is data of type integer. Most programming languages provide for a set of predefined data types, such as integers, real numbers, characters, arrays, pointers, etc. Object-oriented programming languages, however, enable the user (i.e., the programmer) to define new, additional data types.
In C++, a user-defined data type is known as a "class." A class is a set of named data elements (data members) and a set of operations (member functions) designed to manipulate that data. A "class object" is a particular item of data of a particular class.
Object-oriented programming extends the concept of abstract data types to allow relationships to be established between types and "subtypes." This is achieved through a mechanism referred to as "inheritance," a primary characteristic of object-oriented programming. Rather than re-implementing shared characteristics, a class can inherit the data members and member functions of other classes. In C++, for example, inheritance is implemented through the mechanism of "class derivation." One class, known as the "derived class," may inherit the data and functions from another class, known as the "base class." In this manner, an object of the derived class has the characteristics of the base class and, therefore, the derived class can be viewed as a "subtype" of the base class.
A "virtual function" in C++ is a special member function invoked through a base class reference (or pointer), which is bound dynamically at execution (or "run") time. C++ allows a base class pointer to refer not only to an object of its own class, but, alternatively, to a derived class object instead. When a function specified as "virtual" is invoked using such a pointer, the specific function that is called depends on the actual class type of the referenced object. The specific version of the named function which is invoked is one which has been defined by the user to be appropriate to the actual data types (i.e., classes) of the argument or arguments being passed to the function. It is typically a task of the C++ compiler to generate code that will invoke the appropriate function. Selection of the appropriate specific virtual function is desirably transparent to the user.
A "virtual base class" in C++ permits overriding of a default inheritance mechanism. They allow the user to specify a base class to be shared when that base class would otherwise occur more than once in the derivation hierarchy. In particular, a class may be derived from a plurality of other classes, and more than one of these classes may, in turn, be derived from a common base class. Since the default inheritance mechanism uses a tree derivation hierarchy structure, such a derived class will result in the generation of a separate instance of the base class data for each of the multiple occurrences of the common base class. Such multiple instances of what is typically intended as the same data item representing the same information may result in unwanted ambiguity. The use of virtual base classes will avoid this ambiguity.
In C++, the internal system representation of data objects which include virtual functions or virtual base classes contain "hidden" memory pointers which are used for implementing these facilities. In the case of virtual functions, the hidden pointers point to virtual function tables which are used to determine which particular functions are to be called. In the case of virtual base classes, the hidden pointers are used to point to the shared occurrence of a common base class. These pointers are generated by the C++ compilers; they are hidden in that they have not been specified by the user. Therefore, the user typically has no mechanism in C++ by which to directly manipulate their values. Even though these pointers are part of a user created data object, the contents of these pointers cannot be modified by the user. Moreover, the pointers are "volatile" since the location in memory to which they point is only meaningful during the current invocation of the executing program. In other words, the pointers remain valid only for the duration of the program invocation which created them.
It is often advantageous to write data to a mass storage device such as a disk for later retrieval. In many cases it is a different program or a subsequent invocation of the same program which will retrieve the data. For example, a database management program will likely maintain one or more files on disk which contain a collection of data objects which may be retrieved and manipulated by a subsequent invocation of the program. Thus, it is necessary for proper functionality of such an application that the data stored on disk remains valid across multiple program invocations. Data which remains valid across multiple program invocations is called "persistent" data (as opposed to volatile data whose validity is limited to the current invocation of the executing program which created it).
If the data objects stored on disk contain hidden pointers, they will not be directly usable :if read into memory by a different program or by a subsequent invocation of the same program These data objects will be volatile. The hidden pointers may not only contain inaccurate address data in the subsequent invocation, but their use will likely result in illegal memory references. Moreover, the user has no direct mechanism with which to modify these pointers to make them valid, such that they will point to the appropriate information (e.g., virtual function table or shared base class data) in the memory space of the subsequent program invocation.
Such concerns might be addressed by changing the semantics of the C++ language. Alternatively, modifications might be made to the language compiler to alleviate this problem. Such solutions, however, require that the extremely large installed base of C++ compilers and/or C++ programs be modified. Such modifications could adversely effect existing C++ programs and could create incompatibilities between object programs compiled using compilers that differ in this respect. Moreover, such solutions would require the redistribution of many copies of the modified compiler. It would therefore be advantageous to provide a mechanism by which data objects containing hidden pointers can be made persistent without the need to make changes in the semantics of object-oriented languages such as C++.